#ifndef SYMTAB_SYMTAB_H
#define SYMTAB_SYMTAB_H

#include <iostream>
#include <string>
#include <map>
#include <vector>

class symtab;


class sym
{
public:
	sym(const std::string &symName, int symCategory): m_strSymName(symName), m_iSymCategory(symCategory){};
	virtual ~sym(){};
	enum{
		func_name,
		vara_name,
		label_name,
		enum_name,
		type_name,
		struct_union_name,
		other_name
	};
	
public:
	std::string			m_strSymName;
	symtab *			m_pOwnedTab;
	int					m_iSymCategory;
};

class symtab{
public:
	enum {
	scop_gloable,
	scop_function,
	scop_block,
	};
	
	symtab(int scope): m_iScope(scope), m_pPrevTab(NULL){
	};
	
	
	virtual ~symtab()
	{
		SymContainer::iterator it ;
		for(it = m_oSyms.begin(); it!= m_oSyms.end(); ++it)
		{
			delete it->second;
		}
	};
	
	
	sym *			addSym(const std::string &symName, int type)
	{
		sym *pSym = new sym(symName, type);
		if(pSym == NULL)
		{
			std::cout<<"symtab::addSym(const std::string&, int), alloc error"<<std::endl;
			exit(1);
		}
		pSym->m_pOwnedTab = NULL;
		m_oSyms.insert(std::make_pair(symName, pSym));
		return pSym;
	};
	
	
	sym *			findSym(const std::string &symName)
	{
		SymContainer::iterator it = m_oSyms.find(symName);
		if(it == m_oSyms.end())
			return NULL;
		return it->second;
	};
protected:
	typedef std::map<std::string, sym* >		SymContainer;
	
	int								m_iScope;
	SymContainer					m_oSyms;
public:
	symtab *						m_pPrevTab;		//Point to the top symable table.
	std::vector<symtab *>						m_oNextTab;		//Point to the down symable table.
};

extern symtab * pCurSymTab;
extern symtab *	pGloabSymTab;

sym *					findSym(const char * strSym);
sym *					findSym(const sym * pSym);
void					initSymTab();
#endif


